#include "base.h"
#include "test_client.h"
#include "test_server.h"
#include "fnp_psi_client.h"
#include "fnp_psi_server.h"
#include "ibe_apsi_client.h"
#include "ibe_apsi_server.h"
#include "brsa_psi_client.h"
#include "brsa_psi_server.h"
#include "rsa_psi_opt_client.h"
#include "rsa_psi_opt_server.h"
#include "rsa_apsi_opt_client.h"
#include "rsa_apsi_opt_server.h"
#include "jl10_psi_client.h"
#include "jl10_psi_server.h"
#include "bcckls_psi_client.h"
#include "bcckls_psi_server.h"
#include "basic_tool.h"
#include "config.h"

int main(int argc, char * argv[])
{
  Client * pc = NULL;
  Server * ps = NULL;
  ofstream logfile;
  int nbits = 1024;
  if (argc != 9)
    {
      cout<<"./SetInt -p protocol -cf client_input -sf server_input -n nbits"<<endl;
      return -1;
    }
  string protocol, client_file, server_file;
  for (int i = 1; i < 7; i++)
    {
      if (strcmp(argv[i],  "-p") == 0)
        {
          protocol = argv[i+1];
        }
      if (strcmp(argv[i], "-cf") == 0)
        {
          client_file = argv[i+1];
        }
      if (strcmp(argv[i], "-sf") == 0)
        {
          server_file = argv[i+1];
        }
      if (strcmp(argv[i], "-n") == 0)
        {
          nbits = atoi(argv[i+1]);
        }
    }

  if(protocol == "IBE_APSI")
	{
	  pc = new IBE_APSI_Client;
	  ps = new IBE_APSI_Server;
	  logfile.open("ibe_apsi_adapt.log", ios_base::app);
	}
  else if(protocol == "DT10_2_PSI")
	{
	  pc = new BRSA_PSI_Client;
	  ps = new BRSA_PSI_Server;
	  logfile.open("brsa_psi_adapt.log", ios_base::app);
	}
  else if (protocol == "JL10_PSI")
	{
	  pc = new JL10_Client;
	  ps = new JL10_Server;
	  logfile.open("jl09_psi_adapt.log", ios_base::app);
	}
  else if (protocol == "JL09_PSI")
	{
	  pc = new Bcckls_Client;
	  ps = new Bcckls_Server;
	  logfile.open("bcck_psi_adapt.log", ios_base::app);
	}
  else
	{
	  cout<<"no protocol specified"<<endl;
	  return -1;
	}
  //adaptive
  pc->SetAdaptive();
  ps->SetAdaptive();

  pc->SetInputFile(client_file);
  ps->SetInputFile(server_file);

  Memreuse::Initialize(10000, nbits);
  vector<string> output;

  double t_cIni, t_sIni, t_cReq, t_sRes, t_cOnRes;
  size_t s_req = 0, s_resp = 0, s_publish = 0;

  pc->Setup(nbits);
  ps->Setup(nbits);

  BasicTool::F_Time(BasicTool::START);
  pc->Initialize(nbits);
  t_cIni = BasicTool::F_Time(BasicTool::STOP);

  BasicTool::F_Time(BasicTool::START);
  ps->Initialize(nbits);
  t_sIni = BasicTool::F_Time(BasicTool::STOP);

  //adaptive
  ps->PublishData(output);
  s_publish = BasicTool::StringVectorSize(output);
  pc->StoreData(output);
  output.clear();

  int csize = pc->SetSize();
  int ssize = ps->SetSize();

  BasicTool::F_Time(BasicTool::START);
  (pc->*(pc->m_vecRequest[0]))(output);
  t_cReq = BasicTool::F_Time(BasicTool::STOP);

  s_req = BasicTool::StringVectorSize(output);

  BasicTool::F_Time(BasicTool::START);
  (ps->*(ps->m_vecOnRequest[0]))(output);
  t_sRes = BasicTool::F_Time(BasicTool::STOP);

  (ps->*(ps->m_vecResponse[0]))(output);

  s_resp = BasicTool::StringVectorSize(output);

  BasicTool::F_Time(BasicTool::START);
  (pc->*(pc->m_vecOnResponse[0]))(output);
  t_cOnRes = BasicTool::F_Time(BasicTool::STOP);

  // pc->Verify();

  logfile<<csize<<" "<<ssize<<" "<<
	t_cIni<<" "<<t_sIni<<" "<<t_cReq<<" "<<t_sRes<<" "<<t_cOnRes<<" "<<s_req<<" "<<s_resp<<" "<<s_publish<<endl;
  return 0;
}
